home *** CD-ROM | disk | FTP | other *** search
/ ShareWare OnLine 2 / ShareWare OnLine Volume 2 (CMS Software)(1993).iso / os2 / elvis172.zip / unix.c < prev    next >
C/C++ Source or Header  |  1993-03-28  |  5KB  |  228 lines

  1. /* unix.c */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    14407 SW Teal Blvd. #C
  6.  *    Beaverton, OR 97005
  7.  *    kirkenda@cs.pdx.edu
  8.  */
  9.  
  10.  
  11. /* This file contains the unix-specific versions the ttyread() functions.
  12.  * There are actually three versions of ttyread() defined here, because
  13.  * BSD, SysV, and V7 all need quite different implementations.
  14.  */
  15.  
  16. #include "config.h"
  17. #if ANY_UNIX || OS2
  18. # include "vi.h"
  19.  
  20. # if BSD
  21. /* For BSD, we use select() to wait for characters to become available,
  22.  * and then do a read() to actually get the characters.  We also try to
  23.  * handle SIGWINCH -- if the signal arrives during the select() call, then
  24.  * we adjust the o_columns and o_lines variables, and fake a control-L.
  25.  */
  26. #  include <sys/types.h>
  27. #  include <sys/time.h>
  28. int ttyread(buf, len, time)
  29.     char    *buf;    /* where to store the gotten characters */
  30.     int    len;    /* maximum number of characters to read */
  31.     int    time;    /* maximum time to allow for reading */
  32. {
  33.     fd_set    rd;    /* the file descriptors that we want to read from */
  34.     static    tty;    /* 'y' if reading from tty, or 'n' if not a tty */
  35.     int    i;
  36.     struct timeval t;
  37.     struct timeval *tp;
  38.  
  39.  
  40.     /* do we know whether this is a tty or not? */
  41.     if (!tty)
  42.     {
  43.         tty = (isatty(0) ? 'y' : 'n');
  44.     }
  45.  
  46.     /* compute the timeout value */
  47.     if (time)
  48.     {
  49.         t.tv_sec = time / 10;
  50.         t.tv_usec = (time % 10) * 100000L;
  51.         tp = &t;
  52.     }
  53.     else
  54.     {
  55.         tp = (struct timeval *)0;
  56.     }
  57.  
  58.     /* loop until we get characters or a definite EOF */
  59.     for (;;)
  60.     {
  61.         if (tty == 'y')
  62.         {
  63.             /* wait until timeout or characters are available */
  64.             FD_ZERO(&rd);
  65.             FD_SET(0, &rd);
  66.             i = select(1, &rd, (fd_set *)0, (fd_set *)0, tp);
  67.         }
  68.         else
  69.         {
  70.             /* if reading from a file or pipe, never timeout!
  71.              * (This also affects the way that EOF is detected)
  72.              */
  73.             i = 1;
  74.         }
  75.     
  76.         /* react accordingly... */
  77.         switch (i)
  78.         {
  79.           case -1:    /* assume we got an EINTR because of SIGWINCH */
  80.             if (*o_lines != LINES || *o_columns != COLS)
  81.             {
  82. #ifndef CRUNCH
  83.                 *o_nearscroll = 
  84. #endif
  85.                 *o_lines = LINES;
  86.                 *o_columns = COLS;
  87. #ifndef CRUNCH
  88.                 if (!wset)
  89.                 {
  90.                     *o_window = LINES - 1;
  91.                 }
  92. #endif
  93.                 if (mode != MODE_EX)
  94.                 {
  95.                     /* pretend the user hit ^L */
  96.                     *buf = ctrl('L');
  97.                     return 1;
  98.                 }
  99.             }
  100.             break;
  101.     
  102.           case 0:    /* timeout */
  103.             return 0;
  104.     
  105.           default:    /* characters available */
  106.             return read(0, buf, len);
  107.         }
  108.     }
  109. }
  110. # else
  111.  
  112. # if UNIXV || COH_386 || OS2
  113. /* For System-V, we use VMIN/VTIME to implement the timeout.  For no timeout,
  114.  * VMIN should be 1 and VTIME should be 0; for timeout, VMIN should be 0 and
  115.  * VTIME should be the timeout value.
  116.  */
  117. #  include <termio.h>
  118. int ttyread(buf, len, time)
  119.     char    *buf;    /* where to store the gotten characters */
  120.     int    len;    /* maximum number of characters to read */
  121.     int    time;    /* maximum time to allow for reading */
  122. {
  123.     struct termio tio;
  124.     int    bytes;    /* number of bytes actually read */
  125.  
  126.     /* arrange for timeout */
  127.     ioctl(0, TCGETA, &tio);
  128.     if (time)
  129.     {
  130.         tio.c_cc[VMIN] = 0;
  131.         tio.c_cc[VTIME] = time;
  132.     }
  133.     else
  134.     {
  135.         tio.c_cc[VMIN] = 1;
  136.         tio.c_cc[VTIME] = 0;
  137.     }
  138.     ioctl(0, TCSETA, &tio);
  139.  
  140.     /* Perform the read.  Loop if EINTR error happens */
  141.     while ((bytes = read(0, buf, (unsigned)len)) < 0)
  142.     {
  143.         /* probably EINTR error because a SIGWINCH was received */
  144.         if (*o_lines != LINES || *o_columns != COLS)
  145.         {
  146.             *o_lines = LINES;
  147.             *o_columns = COLS;
  148. #ifndef CRUNCH
  149.             if (!wset)
  150.             {
  151.                 *o_nearscroll = LINES;
  152.                 *o_window = LINES - 1;
  153.             }
  154. #endif
  155.             if (mode != MODE_EX)
  156.             {
  157.                 /* pretend the user hit ^L */
  158.                 *buf = ctrl('L');
  159.                 return 1;
  160.             }
  161.         }
  162.     }
  163.  
  164. #ifdef OS2
  165.     if (bytes == 2 && buf[0] == 0)
  166.       buf[0] = '#'; /* extended key */
  167. #endif
  168.  
  169.     /* return the number of bytes read */
  170.     return bytes;
  171.  
  172.     /* NOTE: The terminal may be left in a timeout-mode after this function
  173.      * returns.  This shouldn't be a problem since Elvis *NEVER* tries to
  174.      * read from the keyboard except through this function.
  175.      */
  176. }
  177.  
  178. # else /* any other version of UNIX, assume it is V7 compatible */
  179.  
  180. /* For V7 UNIX (including Minix) we set an alarm() before doing a blocking
  181.  * read(), and assume that the SIGALRM signal will cause the read() function
  182.  * to give up.
  183.  */
  184.  
  185. #include <setjmp.h>
  186.  
  187. static jmp_buf env;
  188.  
  189. /*ARGSUSED*/
  190. SIGTYPE dummy(signo)
  191.     int    signo;
  192. {
  193.     longjmp(env, 1);
  194. }
  195. int ttyread(buf, len, time)
  196.     char    *buf;    /* where to store the gotten characters */
  197.     int    len;    /* maximum number of characters to read */
  198.     int    time;    /* maximum time to allow for reading */
  199. {
  200.     /* arrange for timeout */
  201.     signal(SIGALRM, dummy);
  202.     alarm(time);
  203.  
  204.     /* perform the blocking read */
  205.     if (setjmp(env) == 0)
  206.     {
  207.         len = read(0, buf, (unsigned)len);
  208.     }
  209.     else /* I guess we timed out */
  210.     {
  211.         len = 0;
  212.     }
  213.  
  214.     /* cancel the alarm */
  215.     signal(SIGALRM, dummy); /* <-- to work around a bug in Minix */
  216.     alarm(0);
  217.  
  218.     /* return the number of bytes read */
  219.     if (len < 0)
  220.         len = 0;
  221.     return len;
  222. }
  223.  
  224. # endif /* M_SYSV */
  225. # endif /* !BSD */
  226.  
  227. #endif /* ANY_UNIX */
  228.